/**
 * <h3>Title wheel-utils系统</h3>
 * <h4>Description 工具包</h4>
 * <p>Company 心医国际数字医疗系统（大连） 有限公司</p>
 * <p>Copyright (c) 2019, Senyint. All rights reserved.</p>
 * @author WangNaiFei
 * @version 1.0 <i>2019年3月7日 下午6:55:43</i>
 */
package com.senyint.sys.utils.log;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;

/**
 * <dt>Description:</dt>
 * <dd>日志统一引用，不必每个类声明</dd>
 * <p>
 * 注意：StackTrace 每多一层方法引用多一级
 * 
 * @author WangNaiFei,WangNaiFei@senyint.com
 * @version 1.0 <i>2018年4月2日 下午5:17:45</i> 外部必须先访问getLog方法
 * @version 2.0 <i>2018年4月2日 下午5:17:45</i> 可以作为静态类直接调用
 * @since jdk1.7+
 */
public enum Log {

	INSTANCE;
	private static Logger logger = LoggerFactory.getLogger(Log.class);
	private static Map<String, Logger> logMap = new ConcurrentHashMap<String, Logger>();

	/**
	 * @Fields invokeLevel : 系统调用Log.INSTANCE.debug在StackTrace中的层级
	 */
	public static int classLevel = 3;

	/**
	 * @Title: getLog
	 * @Description: 通过class查找Log，没有创建
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2017年10月11日 上午10:47:18
	 * @version 1.0
	 * @param className
	 * @return
	 */
	private static Logger getLog(String className) {
		Logger log = logMap.get(className);
		if (log == null) {
			logger.debug("==>        add logger {} ({}{}:1)", className, className.substring(className.lastIndexOf(".") + 1), ".java");
			log = LoggerFactory.getLogger(className);
			logMap.put(className, log);
		}
		return log;
	}

	/**
	 * @Title: getLog
	 * @Description: 通过线程查找线程当前类查找Log，没有创建
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2017年10月11日 上午10:47:15
	 * @version 1.0
	 * @return
	 */
	public Logger getLog() {
		return getLog(getStackTraceElement().getClassName());
	}

	// ========================================================================================================

	/**
	 * @Title: formatMessage
	 * @Description: 基础消息格式化
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月11日 下午6:01:27
	 * @version 1.0
	 * @param message
	 * @return
	 */
	public static String formatMessage(String message, Object... args) {
		return new StringBuffer("==> ").append(MessageFormatter.arrayFormat(message, args).getMessage()).toString();
	}

	/**
	 * @Title: trace
	 * @Description: trace
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:14
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public static void trace(Logger log, String message, Object... args) {
		log.trace(formatMessage(message), args);
	}

	/**
	 * @Title: debug
	 * @Description: debug
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:21
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public static void debug(Logger log, String message, Object... args) {
		log.debug(formatMessage(message), args);
	}

	/**
	 * @Title: info
	 * @Description: info
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:10
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public static void info(Logger log, String message, Object... args) {
		log.info(formatMessage(message), args);
	}

	/**
	 * @Title: warn
	 * @Description: warn
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:08
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public static void warn(Logger log, String message, Object... args) {
		log.warn(formatMessage(message), args);
	}

	/**
	 * @Title: error
	 * @Description: error
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:37:53
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public static void error(Logger log, String message, Object... args) {
		log.error(formatMessage(message), args);
	}

	/**
	 * @Title: error
	 * @Description: error
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年4月19日 下午5:47:26
	 * @version 1.0
	 * @param message
	 * @param t
	 */
	public static void error(Logger log, String message, Throwable t) {
		log.error(formatMessage(message), t);
	}
	// ========================================================================================================

	/**
	 * @Title: getStackTraceElement
	 * @Description: 获取当前调用class的堆栈
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年8月23日 下午5:07:13
	 * @version 1.0
	 * @param level
	 * @return
	 */
	public static StackTraceElement getStackTraceElement() {
		return Thread.currentThread().getStackTrace()[classLevel];
	}

	public static StackTraceElement getStackTraceElement(int classLevel) {
		return Thread.currentThread().getStackTrace()[classLevel];
	}

	/**
	 * @Title: formatMessage
	 * @Description: 消息格式化
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月11日 下午3:23:15
	 * @version 1.0
	 * @param stackTraceElement
	 * @param message
	 * @return
	 */
	public static String formatMessage(StackTraceElement stackTraceElement, String type, String message) {
		return new StringBuffer("==> ").append(type).append(stackTraceElement.toString()).append(message).toString();
	}

	/**
	 * @Title: formatMessage
	 * @Description: 消息格式化
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年9月11日 下午6:04:55
	 * @version 1.0
	 * @param stackTraceElement
	 * @param message
	 * @return
	 */
	public static String formatMessage(StackTraceElement stackTraceElement, String message) {
		return new StringBuffer("==> ").append(stackTraceElement.toString()).append(message).toString();
	}

	// ====================================================================================================

	class LogArgument {
		Logger logger;
		String message;

		public LogArgument(StackTraceElement stackTraceElement, String message) {
			this.message = formatMessage(stackTraceElement, message);
			this.logger = getLog(stackTraceElement.getClassName());
		}

		public LogArgument(StackTraceElement stackTraceElement, String type, String message) {
			this.message = formatMessage(stackTraceElement, type, message);
			this.logger = getLog(stackTraceElement.getClassName());
		}
	}

	/**
	 * @Title: trace
	 * @Description: trace
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:14
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public void trace(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.trace(logArgument.message, args);
	}

	/**
	 * @Title: debug
	 * @Description: debug
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:21
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public void debug(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.debug(logArgument.message, args);
	}

	/**
	 * @Title: info
	 * @Description: info
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:10
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public void info(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.info(logArgument.message, args);
	}

	/**
	 * @Title: warn
	 * @Description: warn
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:08
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public void warn(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.warn(logArgument.message, args);
	}

	/**
	 * @Title: error
	 * @Description: error
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:37:53
	 * @version 1.0
	 * @param message
	 * @param args
	 */
	public void error(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.error(logArgument.message, args);
	}

	/**
	 * @Title: error
	 * @Description: error
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年4月19日 下午5:47:26
	 * @version 1.0
	 * @param message
	 * @param t
	 */
	public void error(String message, Throwable t) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), message);
		logArgument.logger.error(logArgument.message, t);
	}

	/**
	 * @Title: registered
	 * @Description: registered
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:38:30
	 * @version 1.0
	 * @param messages
	 */
	public void registered(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), "register", message);
		logArgument.logger.trace(logArgument.message, args);
	}

	/**
	 * @Title: registered
	 * @Description: registered
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年8月23日 下午4:19:46
	 * @version 1.0
	 */
	public void registered() {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), "register", "");
		logArgument.logger.trace(logArgument.message);
	}

	/**
	 * @Title: configured
	 * @Description: configured
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年3月29日 下午11:55:16
	 * @version 1.0
	 * @param messages
	 */
	public void configured(String message, Object... args) {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), "configured", message);
		logArgument.logger.trace(logArgument.message, args);
	}

	/**
	 * @Title: configured
	 * @Description: configured
	 * @author WangNaiFei,WangNaiFei@senyint.com
	 * @date 2018年8月23日 下午4:20:40
	 * @version 1.0
	 */
	public void configured() {
		LogArgument logArgument = new LogArgument(getStackTraceElement(), "configured", "");
		logArgument.logger.trace(logArgument.message);
	}

}